/* ----------------------------------------------------------------------------------------------------------------
 *  SystemManager
 * ----------------------------------------------------------------------------------------------------------------
 */
package pure.engine.core 
{
	import flash.display.DisplayObjectContainer;
	import flash.display.LoaderInfo;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.system.ApplicationDomain;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	import pure.engine.core.ns_despair;

	use namespace ns_despair;
	
	
	// [Internal]
	 
	// 系统管理器
	// [Author] - PURE
	
	// [Hint] - 管理舞台，应用域
	//
public class SystemManager
{
	ns_despair static var m_stage:Stage;

    ns_despair static var m_root:DisplayObjectContainer;

    ns_despair static var m_applicationDomainList:Array = [ ];
    
	

	/**
	 * 初始化
	 * 
	 * @param owner
	 */
	ns_despair static function initialize(owner:DisplayObjectContainer):void
	{
		m_stage = owner.stage;
        m_root   = owner;
	}
	
	
	
	

    /**
     * 加入应用域信息
     * 
     * @param loaderInfo
     */
    ns_despair static function addApplicationDomainInfo(loaderInfo:LoaderInfo):void
    {
        var applicationDomainInfo:ApplicationDomainInfo;
        var len:int,i:int;
        var list:Array;
        var className:String;
        
        list = getSWFClassName(loaderInfo.bytes);
        len = list.length;
        if(len>0)
        {
            for(i = 0;i < len;i++)
            {
                className = list[i];
                if(getDefinition(className))
                {
                    trace('[error] - addApplicationDomainInfo - 类定义 ('+className+' )重复.');
                }
            }
            
			trace('[ApplicationDomainInfo] - added -'+list);
            applicationDomainInfo = new ApplicationDomainInfo()
            applicationDomainInfo.applicationDomain = loaderInfo.applicationDomain;
            applicationDomainInfo.classNameList = list;
            m_applicationDomainList.push(applicationDomainInfo);
        }
    }
    
    
    /**
     * 获取类定义
     * 
     * @param className
     */
	ns_despair static function getDefinition(className:String):Class
	{
        var applicationDomainInfo:ApplicationDomainInfo;
        var len:int,i:int,index:int;
        var def:Class;
        
        len = m_applicationDomainList.length;
        for (i = 0; i < len; i++)
        {
            applicationDomainInfo = m_applicationDomainList[i];
            def =  applicationDomainInfo.getClass(className)
            if(def)
            {
                return def;
            }
        }
        
		if (ApplicationDomain.currentDomain.hasDefinition(className))
		{
			return ApplicationDomain.currentDomain.getDefinition(className) as Class;
		}
        
		return null;
	}
	
	
	/**
	 * 清理
	 */
	ns_despair static function clearup():void
	{
		var applicationDomainInfo:ApplicationDomainInfo;
		var len:int;
		
		len = m_applicationDomainList.length;
		while(--len>-1)
		{
			applicationDomainInfo = m_applicationDomainList[len];
			applicationDomainInfo.dispose();
		}
		m_applicationDomainList.length = 0;
	}
	
	
	
	/**
	 * 拖拽摄像机在世界中移动
	 */
	//private function ____onDragByMouse(e:MouseEvent):void 
	//{
		//_lastX = stage.mouseX;
		//_lastY = stage.mouseY;
		//stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
		//stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
	//}
//
	//
	//private function onMove(e:MouseEvent):void 
	//{
		//scrollInWorld(_lastX - stage.mouseX, _lastY - stage.mouseY);
		//_lastX = stage.mouseX;
		//_lastY = stage.mouseY;
	//}
	//
	//
	//private function onUp(e:MouseEvent):void 
	//{
		//stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
		//stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
	//}

    /**
     * 获取一个swf中的类
     * @param swfBytes
     * @return 
     * 
     */  
    private static var bytes:ByteArray;
    private static var className:Array ;
    private static var tagNum:int ;
    private static function getSWFClassName(swfBytes:ByteArray):Array
    {
        tagNum = 0 ;
        className = [];
        
        bytes = new ByteArray();
        bytes.writeBytes(swfBytes);
        bytes.position = 0;
        bytes.endian = Endian.LITTLE_ENDIAN ;
        
        var compressModal:String ;
        
        compressModal = bytes.readUTFBytes(3);
        if (compressModal != "FWS" && compressModal != "CWS") {
            throw new Error("不能识别的SWF文件格式");
        }
        bytes.readByte()
        bytes.readUnsignedInt();
        bytes.readBytes(bytes);
        bytes.length = bytes.length - 8;
        
        if (compressModal == "CWS") {
            bytes.uncompress();
        }
        bytes.position=13
        
        var tag:int;
        var tagFlag:int;
        var tagLength:int;
        
        var tagBytes:ByteArray ;
        while (bytes.bytesAvailable) {
            readSWFTag(bytes);
        }
        return className.splice(0,className.length);
    }
    
    private static function readSWFTag(tagBytes:ByteArray):void 
    {
        var tag:int=tagBytes.readUnsignedShort();
        //   tracer("tag = " + tag);
        var tagFlag:int=tag >> 6;
        var tagLength:int=tag & 63;   
        if ((tagLength & 63 )== 63) {
            tagLength = tagBytes.readUnsignedInt();
        }
        if (tagFlag == 76) {
            var tagContent:ByteArray=new ByteArray () ;
            if (tagLength != 0) {
                tagBytes.readBytes(tagContent,0,tagLength);
            }
            getClass(tagContent);
        } else {
            tagBytes.position=tagBytes.position + tagLength;
        }
    }
    
    private static function getClass(tagBytes:ByteArray):void {
        var name:String;   
        var readLength:int = readUI16(tagBytes);
        var count:int=0;   
        while (count < readLength) {    
            readUI16(tagBytes);    
            name = readSwfString(tagBytes); 
            
            className.push(name);
            count++;
            tagNum++
            if(tagNum>400){
                return 
            }
        }
    }
    
    private static function readSwfString(tagBytes:ByteArray):String {
        var nameBytes:ByteArray;
        var length:int = 1;
        var num:int = 0;
        var name:String;
        while (true) {
            num = tagBytes.readByte();    
            if (num == 0) {
                nameBytes = new ByteArray () ;
                nameBytes.writeBytes(tagBytes,tagBytes.position - length,length);
                nameBytes.position = 0;
                name=nameBytes.readUTFBytes(length);
                break;
            }
            length++;
        }
        return name;
    }
    
    private static function readUI16(bytes:ByteArray):int {
        var num1:* =bytes.readUnsignedByte();
        var num2:* =bytes.readUnsignedByte();   
        return num1 +(num2 << 8);
    }
	
}
}